package drds.plus.executor.cursor.cursor.impl.common;

import drds.plus.executor.cursor.cursor.Cursor;
import drds.plus.executor.cursor.cursor.IInCursor;
import drds.plus.executor.cursor.cursor.impl.DuplicateValueRowDataLinkedList;
import drds.plus.executor.cursor.cursor.impl.SortingCursor;
import drds.plus.executor.record_codec.RecordCodec;
import drds.plus.executor.record_codec.RecordCodecFactory;
import drds.plus.executor.record_codec.record.FixedLengthRecord;
import drds.plus.executor.record_codec.record.KeyValueRecordPair;
import drds.plus.executor.record_codec.record.Record;
import drds.plus.executor.row_values.RowValues;
import drds.plus.executor.utils.Utils;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.column.Column;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Operation;
import drds.plus.sql_process.abstract_syntax_tree.expression.order_by.OrderBy;

import java.util.*;

/**
 * 专门处理 id in (xx,xx,xx,xx)的cursor 接受一大批的id in请求，然后分批，batch的方式，调用mget拿到具体的值。
 */
public class InCursor extends SortingCursor implements IInCursor {
    Column column = null;
    /**
     * 需要查找的数据
     */
    List<Object> valueList = null;
    Operation operation = null;
    RecordCodec keyRecordCodec;

    RowValues current = null;

    /**
     * 一组返回的记录（size应该<=sizeInOneGo)，分批取出
     */
    List<DuplicateValueRowDataLinkedList> duplicateValueRowDataLinkedListList;
    /**
     * 一组返回记录的指针
     */
    Iterator<DuplicateValueRowDataLinkedList> duplicateValueRowDataLinkedListIterator;
    /**
     * 如果有相同的数据，那么一次取出后。 将这个值缓存在这里，下次可以取出。
     */
    DuplicateValueRowDataLinkedList duplicateValueRowDataLinkedListCache = null;

    public InCursor(Cursor cursor, List<OrderBy> orderByList, Column column, List<Object> valueList, Operation operation) {
        super(cursor, null, orderByList);
        keyRecordCodec = RecordCodecFactory.newRecordCodec(Arrays.asList(Utils.getColumnMetaData(column)));
        this.column = column;
        this.valueList = valueList;
        this.operation = operation;
    }

    protected void init() throws RuntimeException {
        super.init();
    }

    protected void checkInited() throws RuntimeException {
        super.checkInited();
    }

    public boolean skipTo(Record keyRecord) throws RuntimeException {
        throw new IllegalArgumentException("should not be here");
    }

    public boolean skipTo(KeyValueRecordPair keyKeyValueRecordPair) throws RuntimeException {
        throw new IllegalArgumentException("should not be here");
    }

    public Record getKeyRecord(Object value) {
        List list = new ArrayList(1);
        list.add(column);
        FixedLengthRecord record = new FixedLengthRecord(Utils.convertItemListToColumnMetaDataList(list));
        //
        record.put(this.column.getColumnName(), value);
        return record;
    }

    public RowValues current() throws RuntimeException {
        return current;
    }

    public RowValues next() throws RuntimeException {
        if (valueList == null) {
            throw new IllegalArgumentException("value is null ");
        }
        if (duplicateValueRowDataLinkedListIterator == null) {
            // 还未初始化
            List<Record> keyKecordList = new ArrayList<Record>(valueList.size());
            for (Object value : valueList) {
                keyKecordList.add(getKeyRecord(value));
            }
            duplicateValueRowDataLinkedListList = cursor.mgetDuplicateValueRowDataLinkedListList(keyKecordList, false, true);
            duplicateValueRowDataLinkedListIterator = duplicateValueRowDataLinkedListList.iterator();
        }
        /**
         * 简单来说，就是根据sizeInOneGo,从values里面取出指定多的数据。 然后运行一次mget,将结果缓存在当前cursor里面。
         * 提供给外部进行next调用，应该之需要支持next和current吧。暂时 因为数据可能包含多个，比如1->0,1->2 ,
         * 1->3,2->0,2->1这样的数据，应该先将1对应的所有数据全部取尽，再去取第二个。
         */
        if (duplicateValueRowDataLinkedListCache == null) {
            // 两中情况，
            // 一种是duplicate值为空，这时候应该尝试让pairToReturnIterator指针下移。
            // 如pairToReturnIterator也没有数据。则结果集内没有数据,直接返回空。
            if (!duplicateValueRowDataLinkedListIterator.hasNext()) {
                // while end/当前一批没有可以取的数据了。
                setCurrent(null);
                return null;//整体为空返回为null
            } else {
                duplicateValueRowDataLinkedListCache = duplicateValueRowDataLinkedListIterator.next();
            }
        }
        // 取当前值，可能是重复数据的第一个数据，或者也可能是重复数据中
        setCurrent(duplicateValueRowDataLinkedListCache.rowData);
        // 指针下移
        duplicateValueRowDataLinkedListCache = duplicateValueRowDataLinkedListCache.next;
        return current;
    }

    public void setCurrent(RowValues rowData) {
        if (rowData != null) {
            current = rowData;
        }

    }

    public boolean delete() throws RuntimeException {
        throw new IllegalArgumentException("should not be here");
    }

    public Map<Record, DuplicateValueRowDataLinkedList> mgetRecordToDuplicateValueRowDataLinkedListMap(List<Record> keyRecordList, boolean prefixMatch, boolean keyFilterOrValueFilter) throws RuntimeException {
        return parentCursorMgetRecordToDuplicateValueRowDataLinkedListMap(keyRecordList, prefixMatch, keyFilterOrValueFilter);
    }

}
